#include <QApplication>
#include <QAudioOutput>
#include <QWidget>
#include <QPushButton>
#include <QSlider>
#include <QListView>
#include <QLabel>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QMediaPlayer>
#include <QDir>
#include <QStringListModel>
#include <QMessageBox>
#include <QFileInfo>
#include <QRandomGenerator>
#include <QDebug>

class MusicPlayer : public QWidget
{
    Q_OBJECT

public:
    MusicPlayer(QWidget *parent = nullptr) : QWidget(parent)
    {
        setWindowTitle("Simple Music Player (Qt6)");
        resize(450, 320);

        // 枚举播放模式
        enumMode = Sequential;

        // UI
        playButton = new QPushButton("Play", this);
        pauseButton = new QPushButton("Pause", this);
        stopButton = new QPushButton("Stop", this);
        nextButton = new QPushButton("Next", this);
        previousButton = new QPushButton("Previous", this);
        modeButton = new QPushButton("Mode: 顺序", this);
        speedButton = new QPushButton("Speed: 1.0x", this);

        slider = new QSlider(Qt::Horizontal, this);
        slider->setRange(0, 100);

        timeLabel = new QLabel("00:00 / 00:00", this);
        songInfoLabel = new QLabel("No song selected", this);

        // 音频输出
        audio = new QAudioOutput(this);
        audio->setVolume(1.0);

        player = new QMediaPlayer(this);
        player->setAudioOutput(audio);

        // 信号连接
        connect(playButton, &QPushButton::clicked, player, &QMediaPlayer::play);
        connect(pauseButton, &QPushButton::clicked, player, &QMediaPlayer::pause);
        connect(stopButton, &QPushButton::clicked, player, &QMediaPlayer::stop);
        connect(nextButton, &QPushButton::clicked, this, &MusicPlayer::playNext);
        connect(previousButton, &QPushButton::clicked, this, &MusicPlayer::playPrevious);
        connect(modeButton, &QPushButton::clicked, this, &MusicPlayer::switchPlayMode);
        connect(speedButton, &QPushButton::clicked, this, &MusicPlayer::switchPlaybackRate);

        connect(player, &QMediaPlayer::durationChanged, this, &MusicPlayer::onDurationChanged);
        connect(player, &QMediaPlayer::positionChanged, this, &MusicPlayer::onPositionChanged);
        connect(player, &QMediaPlayer::mediaStatusChanged, this, &MusicPlayer::onMediaStatusChanged);
        connect(slider, &QSlider::sliderMoved, player, &QMediaPlayer::setPosition);

        // 歌曲列表
        songListModel = new QStringListModel(this);
        songListView = new QListView(this);
        songListView->setModel(songListModel);
        connect(songListView, &QListView::clicked, this, &MusicPlayer::onSongListViewClicked);

        // 布局
        QVBoxLayout *mainLayout = new QVBoxLayout(this);
        QHBoxLayout *topButtons = new QHBoxLayout();
        topButtons->addWidget(modeButton);
        topButtons->addWidget(speedButton);

        QHBoxLayout *controlLayout = new QHBoxLayout();
        controlLayout->addWidget(previousButton);
        controlLayout->addWidget(playButton);
        controlLayout->addWidget(pauseButton);
        controlLayout->addWidget(stopButton);
        controlLayout->addWidget(nextButton);

        QHBoxLayout *timeLayout = new QHBoxLayout();
        timeLayout->addWidget(timeLabel);

        mainLayout->addLayout(topButtons);
        mainLayout->addWidget(songListView);
        mainLayout->addWidget(songInfoLabel);
        mainLayout->addLayout(controlLayout);
        mainLayout->addWidget(slider);
        mainLayout->addLayout(timeLayout);

        // 加载歌曲
        QDir dir(QCoreApplication::applicationDirPath());
        qDebug() << "程序运行目录:" << dir.absolutePath();
        QStringList entries = dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot);
        for (const QString &entry : entries) qDebug() << " - " << entry;
        if (!dir.cd("Music")) {
            QMessageBox::warning(this, "提示", "未找到 Music 目录。");
            return;
        }

        QStringList songs = dir.entryList(QStringList() << "*.mp3" << "*.wav", QDir::Files);
        if (songs.isEmpty()) {
            QMessageBox::information(this, "提示", "Music 文件夹下没有音频文件。");
            return;
        }

        for (const QString &file : songs) {
            QString path = dir.filePath(file);
            songPaths << path;
            songListModel->insertRow(songListModel->rowCount());
            QModelIndex index = songListModel->index(songListModel->rowCount() - 1);
            songListModel->setData(index, file);
        }

        if (!songPaths.isEmpty()) {
            currentIndex = 0;
            loadAndPlay(currentIndex);
        }
    }

private slots:
    void onDurationChanged(qint64 duration) {
        slider->setMaximum(duration);
        updateTimeLabel(duration, player->position());
    }

    void onPositionChanged(qint64 position) {
        slider->setValue(position);
        updateTimeLabel(player->duration(), position);
    }

    void onMediaStatusChanged(QMediaPlayer::MediaStatus status) {
        if (status == QMediaPlayer::EndOfMedia) {
            if (enumMode == LoopOne) {
                loadAndPlay(currentIndex);
            } else {
                playNext();
            }
        }
    }

    void onSongListViewClicked(const QModelIndex &index) {
        currentIndex = index.row();
        loadAndPlay(currentIndex);
    }

    void playNext() {
        if (songPaths.isEmpty()) return;
        if (enumMode == Random) {
            int next;
            do {
                next = QRandomGenerator::global()->bounded(songPaths.size());
            } while (next == currentIndex && songPaths.size() > 1);
            currentIndex = next;
        } else {
            currentIndex = (currentIndex + 1) % songPaths.size();
        }
        loadAndPlay(currentIndex);
    }

    void playPrevious() {
        if (songPaths.isEmpty()) return;
        currentIndex = (currentIndex - 1 + songPaths.size()) % songPaths.size();
        loadAndPlay(currentIndex);
    }

    void switchPlayMode() {
        enumMode = static_cast<PlayMode>((enumMode + 1) % 3);
        switch (enumMode) {
        case Sequential: modeButton->setText("Mode: 顺序"); break;
        case LoopOne:    modeButton->setText("Mode: 单曲循环"); break;
        case Random:     modeButton->setText("Mode: 随机"); break;
        }
    }

    void switchPlaybackRate() {
        static const QList<qreal> speeds = {1.0, 1.25, 1.5, 2.0};
        static int index = 0;
        index = (index + 1) % speeds.size();
        player->setPlaybackRate(speeds[index]);
        speedButton->setText(QString("Speed: %1x").arg(speeds[index]));
    }

private:
    enum PlayMode { Sequential, LoopOne, Random };
    PlayMode enumMode;

    void loadAndPlay(int index) {
        if (index < 0 || index >= songPaths.size()) return;
        player->setSource(QUrl::fromLocalFile(songPaths[index]));
        player->play();
        QString fileName = QFileInfo(songPaths[index]).fileName();
        songInfoLabel->setText("Now playing: " + fileName);
    }

    void updateTimeLabel(qint64 total, qint64 current) {
        auto formatTime = [](qint64 ms) {
            int secs = ms / 1000;
            int mins = secs / 60;
            secs = secs % 60;
            return QString("%1:%2").arg(mins, 2, 10, QChar('0')).arg(secs, 2, 10, QChar('0'));
        };
        timeLabel->setText(formatTime(current) + " / " + formatTime(total));
    }

    QMediaPlayer *player;
    QAudioOutput *audio;
    QStringList songPaths;
    int currentIndex = 0;

    QPushButton *playButton;
    QPushButton *pauseButton;
    QPushButton *stopButton;
    QPushButton *nextButton;
    QPushButton *previousButton;
    QPushButton *modeButton;
    QPushButton *speedButton;
    QSlider *slider;
    QListView *songListView;
    QLabel *timeLabel;
    QLabel *songInfoLabel;
    QStringListModel *songListModel;
};

#include "main.moc"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MusicPlayer player;
    player.show();
    return app.exec();
}
